package com.simple.common.sms;

import com.alibaba.fastjson2.JSONObject;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.simple.common.constant.BaseMatches;
import com.simple.common.constant.CommonConstants;
import com.simple.common.exception.ServiceException;
import com.simple.framework.config.SmsConfiguration;
import com.simple.framework.core.redis.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @Description 发送短信
 * @Author xiaoke
 * @Date 2024/8/10 18:00
 * @Version 1.0
 */
@Slf4j
@Component
public class SmsMessageService {

    private final SmsConfiguration smsConfiguration;

    private final RedisService redisService;

    public SmsMessageService(SmsConfiguration smsConfiguration, RedisService redisService) {
        this.smsConfiguration = smsConfiguration;
        this.redisService = redisService;
    }

    /**
     * 使用AK&SK初始化账号Client
     *
     * @return Client
     * @throws Exception 可能有异常
     */
    private Client createClient() throws Exception {
        Config config = new Config()
                .setAccessKeyId(smsConfiguration.getAccessKeyId())
                .setAccessKeySecret(smsConfiguration.getAccessKeySecret());
        config.endpoint = smsConfiguration.getEndpoint();
        return new Client(config);
    }

    /**
     * 发送短信验证码
     *
     * @param phone 手机号
     * @param code  验证码（留空则使用默认生成规则）
     */
    public boolean sendVerificationCode(String phone, String code) {
        if (!phone.matches(BaseMatches.phoneMatches)) {
            throw new ServiceException("手机号格式错误");
        }
        Client client;
        try {
            client = createClient();
        } catch (Exception e) {
            log.info("阿里云短信服务-初始化失败：",e);
            return false;
        }
        JSONObject templateParam = new JSONObject();
        // 默认获取6位数字验证码
        if(code == null || code.length() == 0) {
            code = generateVerificationCode(6);
        }
        templateParam.put("code", code);
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setPhoneNumbers(phone)
                .setTemplateCode(smsConfiguration.getTemplateCode())
                .setTemplateParam(templateParam.toJSONString())
                .setSignName(smsConfiguration.getSignName());
        JSONObject jsonObject = null;
        try {
            // 发送短信
            SendSmsResponse response = client.sendSmsWithOptions(sendSmsRequest, new RuntimeOptions());
            jsonObject = (JSONObject) JSONObject.parseObject(JSONObject.toJSONString(response)).get("body");
            if(jsonObject.get("code").equals("OK")) {
                log.info("阿里云短信发送成功！手机号：【{}】 -- 验证码：【{}】",phone,code);
                cacheSmsCode(phone, code);
                return true;
            }else {
                log.info("阿里云短信发送失败 {} ，手机号：【{}】 -- 验证码：【{}】",jsonObject,phone,code);
            }
        } catch (Exception ex) {
            log.error("阿里云短信发送出现异常：{}",ex.getMessage());
            ex.printStackTrace();
        }
        return false;
    }

    /**
     * 缓存验证码（5分钟）
     *
     * @param phone 手机号
     * @param code  验证码
     */
    private void cacheSmsCode(String phone, String code) {
        // 缓存验证码
        redisService.setCacheObject(CommonConstants.SMS_VALUE+phone,code,5L, TimeUnit.MINUTES);
    }

    /**
     * 校验验证码
     *
     * @param phone 手机号
     * @param code  验证码
     */
    public void checkVerificationCode(String phone, String code) {
        String key = CommonConstants.SMS_VALUE+phone;
        if (redisService.getCacheObject(key) == null) {
            throw new ServiceException("验证码已过期");
        }
        if (!redisService.getCacheObject(key).equals(code)) {
            throw new ServiceException("验证码错误");
        }
    }

    /**
     * 清除验证码
     *
     * @param phone 手机号
     */
    public void clearVerificationCode(String phone) {
        String key = CommonConstants.SMS_VALUE+phone;
        redisService.deleteObject(key);
    }


   /**
     * 生成验证码
     *
     * @param num 验证码位数
     * @return 验证码
     */
    private  String generateVerificationCode(int num) {
        Random random = new Random();
        StringBuilder codeBuilder = new StringBuilder();
        for (int i = 0; i < num; i++) {
            // nextInt(10) 生成0到9的随机数
            int digit = random.nextInt(10);
            codeBuilder.append(digit);
        }
        return codeBuilder.toString();
    }

}